﻿using Server.Database;
using Server.Business.proto;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Server.Resource;
using MongoDB.Bson;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace Server.Business
{
    public class ProdBusiness
    {
        private MongoDatabase _database;
        private MongoCollection<ProdDB> _prodArray;
        private MongoCollection<SignDB> _signArray;

        private MongoCollection<ProdDB> ProdArray
        {
            get
            {
                if (_prodArray == null)
                    _prodArray = Database.GetCollection<ProdDB>("ProdDB");
                return _prodArray;
            }
        }

        private MongoCollection<SignDB> SignArray
        {
            get
            {
                if (_signArray == null)
                    _signArray = Database.GetCollection<SignDB>("SignDB");
                return _signArray;
            }
        }

        private MongoDatabase Database
        {
            get
            {
                if (_database == null)
                {
                    MongoClient client = new MongoClient(ServerConfig.Singleton.Database);
                    MongoServer server = client.GetServer();
                    _database = server.GetDatabase("zcdb");
                }
                return _database;
            }
        }

        public void SignLable(string name)
        {
            var query = Query.EQ("Name", name);
            var item = SignArray.FindOne(query);
            if (item != null && item.IsMain == 0)
            {
                var update = Update.Set("IsMain", 1);
                SignArray.Update(query, update);
            }
            else
            {
                SignArray.Insert(new SignDB() { Name = name, IsMain = 1 });
            }
        }

        public void UnSignLable(string name)
        {
            var query = Query.EQ("Name", name);
            var item = SignArray.FindOne(query);
            if (item != null && item.IsMain == 1)
            {
                var update = Update.Set("IsMain", 0);
                SignArray.Update(query, update);
            }
        }

        public byte[] SearchProdName()
        {
            var query1 = (from r in ProdArray.FindAll()
                          where !string.IsNullOrEmpty(r.ProdLabel)
                          orderby r.PicFolder
                          select r.ProdLabel.ToUpper()).Distinct();

            IEnumerable<SignDB> signs = SignArray.Find(Query.EQ("IsMain", 1));

            SignLabelArray.Builder builder = new SignLabelArray.Builder();
            foreach (string s in query1)
            {
                bool isMain = false;
                foreach (SignDB sign in signs)
                {
                    if (sign.Name == s)
                    {
                        isMain = true;
                        break;
                    }
                }

                builder.SignLabelList.Add(new SignLabel.Builder()
                    .SetName(s)
                    .SetIsMain(isMain ? 1 : 0)
                    .Build());
                    
            }

            return builder.Build().ToByteArray();
        }

        public string AddProd(ProdDB prod)
        {
            ProdArray.Insert(prod);
            return prod.Id.ToString();
        }

        public string AddProd(Prod prod)
        {
            ProdDB proddb = new ProdDB();
            proddb.ProdClass = prod.ProdClass;
            proddb.ProdLabel = prod.ProdLabel;
            proddb.ProdPlace = prod.ProdPlace;
            proddb.ProdSeries = prod.ProdSeries;
            proddb.ProdVersion = prod.ProdVersion;
            proddb.PhyColor = prod.PhyColor;
            proddb.PhyDefend = prod.PhyDefend;
            proddb.PhyImpact = prod.PhyImpact;
            proddb.PhySize = prod.PhySize;
            proddb.AdpClass = prod.AdpClass;
            proddb.AdpColor = prod.AdpColor;
            proddb.AdpCri = prod.AdpCri;
            proddb.EleLgtPower = prod.EleLgtPower;
            proddb.OptAngle = prod.OptAngle;
            proddb.ProjSetup = prod.ProjSetup;
            proddb.BusMarket = prod.BusMarket;

            proddb.ProdOrgin = prod.ProdOrgin;
            proddb.PhyMaterial = prod.PhyMaterial;
            proddb.PhyWeight = prod.PhyWeight;
            proddb.OptExplain = prod.OptExplain;
            proddb.OptEff = prod.OptEff;
            proddb.EleShock = prod.EleShock;
            proddb.EleVoltage = prod.EleVoltage;
            proddb.EleType = prod.EleType;
            proddb.ElePower = prod.EleElecPower;
            proddb.EleAllPower = prod.EleAllPower;
            proddb.EleCtlType = prod.EleCtlType;
            proddb.AdpVersion = prod.AdpVersion;
            proddb.AdpOutput = prod.AdpOutput;
            proddb.AdpPins = prod.AdpPins;
            proddb.ProjParts = prod.ProjParts;
            proddb.ProjSize = prod.ProjSize;
            proddb.ProjReport = prod.ProjReport;
            proddb.ProjBaikup = prod.ProjBaikup;

            proddb.BusIn = prod.BusIn;
            proddb.BusOut = prod.BusOut;
            proddb.BusExpires = prod.BusExpires;

            proddb.PicFolder = DateTime.Now.ToString("yyyyMMddHHmmss");
            Directory.CreateDirectory(Path.Combine(ServerConfig.Singleton.ImgRoot, proddb.PicFolder));

            if (prod.HasUploadFacade)
            {
                proddb.PicFacade = CreateImage(
                    proddb.PicFolder,
                    "f",
                    prod.UploadFacade.ToByteArray(),
                    ProdDB.Zoom70,
                    ProdDB.Zoom100,
                    ProdDB.Zoom150);
            }

            if (prod.HasUploadGrading)
            {
                proddb.PicFacade = CreateImage(
                    proddb.PicFolder,
                    "g",
                    prod.UploadGrading.ToByteArray(),
                    ProdDB.Zoom100);
            }

            if (prod.HasUploadSize)
            {
                proddb.PicFacade = CreateImage(
                    proddb.PicFolder,
                    "s",
                    prod.UploadSize.ToByteArray(),
                    ProdDB.Zoom100);
            }

            if (prod.HasUploadLive)
            {
                proddb.PicFacade = CreateImage(
                    proddb.PicFolder,
                    "l",
                    prod.UploadLive.ToByteArray(),
                    ProdDB.Zoom100);
            }

            ProdArray.Insert(proddb);
            return prod.ToString();
        }

        public ProdDB GetProd(string id)
        {
            return ProdArray.FindOne(Query.EQ("_id", ObjectId.Parse(id)));
        }

        public bool UpdateProd(Prod target)
        {
            IMongoQuery query = Query.EQ("_id", ObjectId.Parse(target.Id));
            ProdDB source = ProdArray.FindOne(query);
            List<UpdateBuilder> parameters = new List<UpdateBuilder>();
            if(source.ProdClass != target.ProdClass)
                parameters.Add(Update.Set("ProdClass", target.ProdClass));
            if(source.ProdLabel != target.ProdLabel)
                parameters.Add(Update.Set("ProdLabel", target.ProdLabel));
            if(source.ProdPlace != target.ProdPlace)
                parameters.Add(Update.Set("ProdPlace", target.ProdPlace));
            if(source.ProdSeries != target.ProdSeries)
                parameters.Add(Update.Set("ProdSeries", target.ProdSeries));
            if(source.ProdVersion != target.ProdVersion)
                parameters.Add(Update.Set("ProdVersion", target.ProdVersion));
            if(source.PhyColor != target.PhyColor)
                parameters.Add(Update.Set("PhyColor", target.PhyColor));
            if(source.PhyDefend != target.PhyDefend)
                parameters.Add(Update.Set("PhyDefend", target.PhyDefend));
            if(source.PhyImpact != target.PhyImpact)
                parameters.Add(Update.Set("PhyImpact", target.PhyImpact));
            if(source.PhySize != target.PhySize)
                parameters.Add(Update.Set("PhySize", target.PhySize));
            if(source.AdpClass != target.AdpClass)
                parameters.Add(Update.Set("AdpClass", target.AdpClass));
            if(source.AdpColor != target.AdpColor)
                parameters.Add(Update.Set("AdpColor", target.AdpColor));
            if(source.AdpCri != target.AdpCri)
                parameters.Add(Update.Set("AdpCri", target.AdpCri));
            if(source.EleLgtPower != target.EleLgtPower)
                parameters.Add(Update.Set("EleLgtPower", target.EleLgtPower));
            if(source.OptAngle != target.OptAngle)
                parameters.Add(Update.Set("OptAngle", target.OptAngle));
            if(source.ProjSetup != target.ProjSetup)
                parameters.Add(Update.Set("ProjSetup", target.ProjSetup));
            if(source.BusMarket != target.BusMarket)
                parameters.Add(Update.Set("BusMarket", target.BusMarket));


            if(source.ProdOrgin != target.ProdOrgin)
                parameters.Add(Update.Set("ProdOrgin", target.ProdOrgin));
            if(source.PhyMaterial != target.PhyMaterial)
                parameters.Add(Update.Set("PhyMaterial", target.PhyMaterial));
            if(source.PhyWeight != target.PhyWeight)
                parameters.Add(Update.Set("PhyWeight", target.PhyWeight));
            if(source.OptExplain != target.OptExplain)
                parameters.Add(Update.Set("OptExplain", target.OptExplain));
            if(source.OptEff != target.OptEff)
                parameters.Add(Update.Set("OptEff", target.OptEff));
            if(source.EleShock != target.EleShock)
                parameters.Add(Update.Set("EleShock", target.EleShock));
            if(source.EleVoltage != target.EleVoltage)
                parameters.Add(Update.Set("EleVoltage", target.EleVoltage));
            if(source.EleType != target.EleType)
                parameters.Add(Update.Set("EleType", target.EleType));
            if(source.ElePower != target.EleElecPower)
                parameters.Add(Update.Set("ElePower", target.EleElecPower));
            if(source.EleAllPower != target.EleAllPower)
                parameters.Add(Update.Set("EleAllPower", target.EleAllPower));
            if(source.EleCtlType != target.EleCtlType)
                parameters.Add(Update.Set("EleCtlType", target.EleCtlType));
            if(source.AdpVersion != target.AdpVersion)
                parameters.Add(Update.Set("AdpVersion", target.AdpVersion));
            if(source.AdpOutput != target.AdpOutput)
                parameters.Add(Update.Set("AdpOutput", target.AdpOutput));
            if(source.AdpPins != target.AdpPins)
                parameters.Add(Update.Set("AdpPins", target.AdpPins));
            if(source.ProjParts != target.ProjParts)
                parameters.Add(Update.Set("ProjParts", target.ProjParts));
            if(source.ProjSize != target.ProjSize)
                parameters.Add(Update.Set("ProjSize", target.ProjSize));
            if(source.ProjReport != target.ProjReport)
                parameters.Add(Update.Set("ProjReport", target.ProjReport));
            if(source.ProjBaikup != target.ProjBaikup)
                parameters.Add(Update.Set("ProjBaikup", target.ProjBaikup));

            if(source.BusIn != target.BusIn)
                parameters.Add(Update.Set("BusIn", target.BusIn));
            if(source.BusOut != target.BusOut)
                parameters.Add(Update.Set("BusOut", target.BusOut));
            if(source.BusExpires != target.BusExpires)
                parameters.Add(Update.Set("BusExpires", target.BusExpires));

            string folder = target.PicFolder;
            if (target.HasUploadFacade)
            {
                string picFacade = CreateImage(
                    folder,
                    "f",
                    target.UploadFacade.ToByteArray(),
                    ProdDB.Zoom70,
                    ProdDB.Zoom100,
                    ProdDB.Zoom150);

                parameters.Add(Update.Set("PicFacade", picFacade));
            }

            if (target.HasUploadGrading)
            {
                string picFacade = CreateImage(
                    target.PicFolder,
                    "g",
                    target.UploadGrading.ToByteArray(),
                    ProdDB.Zoom100);
                parameters.Add(Update.Set("picFacade", picFacade));
            }

            if (target.HasUploadSize)
            {
                string picFacade = CreateImage(
                    target.PicFolder,
                    "s",
                    target.UploadSize.ToByteArray(),
                    ProdDB.Zoom100);
                parameters.Add(Update.Set("PicSize", picFacade));
            }

            if (target.HasUploadLive)
            {
                string picFacade = CreateImage(
                    target.PicFolder,
                    "l",
                    target.UploadLive.ToByteArray(),
                    ProdDB.Zoom100);
                parameters.Add(Update.Set("PicLive", picFacade));
            }

            if(parameters.Count == 0)
                return true;

            UpdateBuilder update = parameters[0];
            for(int i=1;i<parameters.Count -1;i++)
            {
                update.Combine(parameters[i]);
            }

            return ProdArray.Update(query, update).Ok;
        }

        private string CreateImage(string folder, string prefix, byte[] bytes, params int[] zoomLevels)
        {
            string imageFolder = Path.Combine(ServerConfig.Singleton.ImgRoot, folder);

            string fileName = string.Format("{0}{1}.jpg", prefix, DateTime.Now.ToString("yyyyMMddHHmmss"));
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                Image bmpImage = Image.FromStream(ms);
                bmpImage.Save(Path.Combine(imageFolder, fileName), ImageFormat.Jpeg);

                foreach (int zoolLevel in zoomLevels)
                {
                    string resizedUrl = Path.Combine(imageFolder, zoolLevel.ToString(), fileName);
                    if (!File.Exists(resizedUrl))
                    {
                        Image resized = ResizeImage(bmpImage, new Size(zoolLevel, zoolLevel));
                        resized.Save(resizedUrl, ImageFormat.Jpeg);
                        resized.Dispose();
                    }
                }
            }

            return fileName;

        }

        private Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true)
        {
            int newWidth;
            int newHeight;
            if (preserveAspectRatio)
            {
                int originalWidth = image.Width;
                int originalHeight = image.Height;
                float percentWidth = (float)size.Width / (float)originalWidth;
                float percentHeight = (float)size.Height / (float)originalHeight;
                float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
                newWidth = (int)(originalWidth * percent);
                newHeight = (int)(originalHeight * percent);
            }
            else
            {
                newWidth = size.Width;
                newHeight = size.Height;
            }
            Image newImage = new Bitmap(newWidth, newHeight);
            using (Graphics graphicsHandle = Graphics.FromImage(newImage))
            {
                graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
            }
            return newImage;

            //Image original = Image.FromFile(@"D:\Test\test.jpg");
            //Image resized = ResizeImage(original, new Size(50, 50));
            //resized.Save(@"D:\Test\resize.jpg", ImageFormat.Jpeg);
        }

        public bool DeleteProd(string id)
        {
            return ProdArray.Remove(Query.EQ("_id", ObjectId.Parse(id))).Ok;
        }

        #region 产品分类搜索

        // 二级页面
        public byte[] SearchProdClass(byte[] conditions)
        {
            CondProdClass cond = CondProdClass.ParseFrom(conditions);
            List<IMongoQuery> queryArray = new List<IMongoQuery>();
            if (cond.HasClass)
                queryArray.Add(Query.EQ("ProdClass", cond.Class));

            if (cond.HasSetup)
            {
                if (cond.Setup == 7)
                    queryArray.Add(Query.Or(Query.EQ("ProjSetup", 1), Query.EQ("ProjSetup", 2)));
                else
                    queryArray.Add(Query.EQ("ProjSetup", cond.Setup));
            }

            if (cond.HasUsePlace)
                queryArray.Add(Query.EQ("ProdPlace", cond.UsePlace));

            HashSet<string> hashSet = new HashSet<string>();

            StringBuilder sb = new StringBuilder();
            foreach (ProdDB prod in ProdArray.Find(Query.And(queryArray.ToArray())))
            {
                sb.AppendFormat("{0},", prod.ProdLabel);
                sb.AppendFormat("{0},", prod.ProdSeries);
                sb.AppendFormat("{0},", prod.AdpClass);

                string path = string.Empty;
                if (!string.IsNullOrEmpty(prod.PicFolder) && !string.IsNullOrEmpty(prod.PicFacade))
                    path = string.Format("{0}/{1}/{2}", prod.PicFolder, ProdDB.Zoom150, prod.PicFacade);

                sb.AppendFormat("{0},", path);
                hashSet.Add(sb.ToString());
                sb.Clear();
            }

            ProdClassArray.Builder arrayBuilder = new ProdClassArray.Builder();
            foreach (string str in hashSet)
            {
                string[] array = str.Split(',');

                ProdClass.Builder itemBuilder = new ProdClass.Builder();

                if (!string.IsNullOrEmpty(array[0]))
                    itemBuilder.SetProdLabel(array[0]);
                if (!string.IsNullOrEmpty(array[1]))
                    itemBuilder.SetProdSeries(array[1]);

                int value;
                if (int.TryParse(array[2], out value))
                    itemBuilder.SetAdpClass(value);

                itemBuilder.SetPicFacade(array[3]);
                arrayBuilder.ProdClassList.Add(itemBuilder.Build());
            }

            return arrayBuilder.Build().ToByteArray();
        }

        #endregion

        #region 产品系列搜索

        public IEnumerable<ProdDB> InnerSearchProdSeries(byte[] conditions)
        {
            List<IMongoQuery> queryArray = new List<IMongoQuery>();
            CondProdSeries cond1 = CondProdSeries.ParseFrom(conditions);

            if (cond1.HasProductClass)
                queryArray.Add(Query.EQ("ProdClass", cond1.ProductClass));

            if (cond1.HasUsePlace)
                queryArray.Add(Query.EQ("ProdPlace", cond1.UsePlace));

            if (cond1.HasSeries)
                queryArray.Add(Query.EQ("ProdSeries", cond1.Series));

            if (cond1.HasAdpaterClass)
                queryArray.Add(Query.EQ("AdpClass", cond1.AdpaterClass));

            if (cond1.HasSetup)
            {
                if (cond1.Setup == 7)
                    queryArray.Add(Query.Or(Query.EQ("ProjSetup", 1), Query.EQ("ProjSetup", 2)));
                else
                    queryArray.Add(Query.EQ("ProjSetup", cond1.Setup));
            }

            IEnumerable<ProdDB> result = null;
            if (cond1.HasLable)
            {
                result = from r in ProdArray.Find(Query.And(queryArray.ToArray()))
                         where !string.IsNullOrEmpty(r.ProdLabel)
                             && r.ProdLabel.ToUpper() == cond1.Lable.ToUpper()
                         orderby r.ProdLabel ascending, r.PicFolder descending
                         select r;
            }
            else
            {
                result = from r in ProdArray.Find(Query.And(queryArray.ToArray()))
                         orderby r.ProdLabel ascending, r.PicFolder descending
                         select r;
            }

            if (cond1.HasFacade)
            {
                result = from r in result
                         let facade = string.Format("{0}/{1}/{2}", r.PicFolder, ProdDB.Zoom150, r.PicFacade)
                         where facade == cond1.Facade
                         select r;
            }

            return result;
        }

        // 三级页面
        public byte[] SearchProdSeries(byte[] conditions)
        {
            ProdViewArray.Builder builder = new ProdViewArray.Builder();
            foreach (ProdDB prod in InnerSearchProdSeries(conditions))
            {
                builder.ViewList.Add(ConverToView(prod));
            }

            return builder.Build().ToByteArray();
        }

        public string SearchProdSeriesToPDF(byte[] conditions)
        {
            ListGenerator generator = new ListGenerator();
            return generator.Generate(InnerSearchProdSeries(conditions), true);
        }

        public string SearchProdSeriesToExcel(byte[] conditions)
        {
            ListGenerator generator = new ListGenerator();
            return generator.Generate(InnerSearchProdSeries(conditions));
        }

        private void Log(string message)
        {
            if (ServerConfig.Singleton.Debug)
                LogService.Log(new LogDB() { Action = message });
        }

        #endregion

        #region 主界面搜索

        public IEnumerable<ProdDB> InnerSearchProdList(byte[] conditions)
        {
            List<IMongoQuery> queryArray = new List<IMongoQuery>();
            CondPordList cond = CondPordList.ParseFrom(conditions);

            if (cond.HasSeries)
                queryArray.Add(Query.EQ("ProdSeries", cond.Series));
   
            if (cond.HasUsePlace)
                queryArray.Add(Query.EQ("ProdPlace", cond.UsePlace));

            if (cond.HasProductClass)
                queryArray.Add(Query.EQ("ProdClass", cond.ProductClass));

            if (cond.HasProductVersion)
                queryArray.Add(Query.EQ("ProdVersion", cond.ProductVersion));

            if (cond.HasLightingSourceClass)
                queryArray.Add(Query.EQ("AdpClass", cond.LightingSourceClass));

            if(cond.HasSetup)
                queryArray.Add(Query.EQ("ProjSetup", cond.Setup));

            if (cond.HasStartLightingPower && cond.HasEndLightingPower)
                queryArray.Add(Query.And(Query.GTE("EleLgtPower", cond.StartLightingPower), Query.LTE("EleLgtPower", cond.EndLightingPower)));
            else if (cond.HasStartLightingPower)
                queryArray.Add(Query.GTE("EleLgtPower", cond.StartLightingPower));
            else if (cond.HasEndLightingPower)
                queryArray.Add(Query.LTE("EleLgtPower", cond.EndLightingPower));

            if (cond.HasCri)
            {
                switch (cond.Cri)
                {
                    case 1:
                        queryArray.Add(Query.And(Query.GT("AdpCri", 0), Query.LTE("AdpCri", 79)));
                        break;
                    case 2:
                        queryArray.Add(Query.And(Query.GTE("AdpCri", 80), Query.LTE("AdpCri", 89)));
                        break;
                    case 3:
                        queryArray.Add(Query.GT("AdpCri", 90));
                        break;
                }
            }

            if (cond.HasStartMarketPrice && cond.HasEndMarketPrice)
                queryArray.Add(Query.And(Query.GTE("BusMarket", cond.StartMarketPrice), Query.LTE("BusMarket", cond.EndMarketPrice)));
            else if (cond.HasStartMarketPrice)
                queryArray.Add(Query.GTE("BusMarket", cond.StartMarketPrice));
            else if (cond.HasEndMarketPrice)
                queryArray.Add(Query.LTE("BusMarket", cond.EndMarketPrice));

            IEnumerable<ProdDB> query = null;
            if (queryArray.Count > 0)
                query = from r in ProdArray.Find(Query.And(queryArray.ToArray())) 
                        orderby r.ProdLabel ascending, r.PicFolder descending
                        select r;
            else
                query = from r in ProdArray.FindAll()
                        orderby r.ProdLabel ascending, r.PicFolder descending
                        select r;

                //4.	光源色温下拉菜单分为三档暖<3300K
                //中性白 3300K-5000K
                //冷>5000K
                if (cond.HasColor)
                {
                    switch (cond.Color)
                    {
                        case 1:
                            query = from r in query
                                    let value = TryParseValue(r.AdpColor)
                                    where value > 0 && value < 3300
                                    select r;
                            break;
                        case 2:
                            query = from r in query
                                    let value = TryParseValue(r.AdpColor)
                                    where value >= 3300 && value <= 5000
                                    select r;
                            break;
                        case 3:
                            query = from r in query
                                    let value = TryParseValue(r.AdpColor)
                                    where value > 5000
                                    select r;
                            break;
                    }
                }

            // 灯具配光
            if (cond.HasAngle)
            {
                switch (cond.Angle)
                {
                    case 1:
                        query = from r in query
                                let value = TryParseValue(r.OptAngle)
                                where value > 0 && value <= 8
                                select r;
                        break;
                    case 2:
                        query = from r in query
                                let value = TryParseValue(r.OptAngle)
                                where value >= 9 && value <= 15
                                select r;
                        break;
                    case 3:
                        query = from r in query
                                let value = TryParseValue(r.OptAngle)
                                where value >= 16 && value <= 25
                                select r;
                        break;
                    case 4:
                        query = from r in query
                                let value = TryParseValue(r.OptAngle)
                                where value >= 26 && value <= 39
                                select r;
                        break;
                    case 5:
                        query = from r in query
                                let value = TryParseValue(r.OptAngle)
                                where value >= 40
                                select r;
                        break;
                    case 6:
                        query = from r in query
                                where r.OptAngle == "WW"
                                select r;
                        break;
                    case 7:
                        query = from r in query
                                where r.OptAngle == "ST"
                                select r;
                        break;
                    case 8:
                        query = from r in query
                                let value = TryParseValue(r.OptAngle)
                                where value == 0 && r.OptAngle != "WW" && r.OptAngle != "ST"
                                select r;
                        break;
                }
            }

            if (cond.HasProductLable)
            {
                query = from r in query
                        where !string.IsNullOrEmpty(r.ProdLabel)
                            && r.ProdLabel.ToUpper() == cond.ProductLable.ToUpper()
                        select r;
            }

            return query;
        }

        private int TryParseValue(string value)
        {
            if (string.IsNullOrEmpty(value))
                return 0;

            int intValue;
            if (int.TryParse(value, out intValue))
                return intValue;
            return 0;
        }

        private ProdView ConverToView(ProdDB prod)
        {
            ProdView.Builder builder = new ProdView.Builder();
            builder.SetId(prod.Id.ToString());

            if (!string.IsNullOrEmpty(prod.PicFolder) && !string.IsNullOrEmpty(prod.PicFacade))
            {
                string path = string.Format("{0}/{1}/{2}", prod.PicFolder, ProdDB.Zoom70, prod.PicFacade);
                builder.SetPicFacade(path);
            }

            if (!string.IsNullOrEmpty(prod.ProdSeries))
                builder.SetProdSeries(prod.ProdSeries);

            builder.SetProdClass(prod.ProdClass);

            if (!string.IsNullOrEmpty(prod.ProdVersion))
                builder.SetProdVersion(prod.ProdVersion);

            if (!string.IsNullOrEmpty(prod.ProdLabel))
                builder.SetProdLabel(prod.ProdLabel);

            if (!string.IsNullOrEmpty(prod.PhySize))
                builder.SetPhySize(prod.PhySize);

            builder.SetAdpClass(prod.AdpClass);
            builder.SetEleLgtPower(prod.EleLgtPower);

            if (!string.IsNullOrEmpty(prod.AdpColor))
                builder.SetAdpColor(prod.AdpColor);

            builder.SetAdpCri(prod.AdpCri);

            if (!string.IsNullOrEmpty(prod.OptAngle))
                builder.SetOptAngle(prod.OptAngle);

            builder.SetBusMarket(prod.BusMarket);
            return builder.Build();
        }

        // 三级搜索界面
        public byte[] SearchProdList(byte[] conditions)
        {
            ProdViewArray.Builder arrayBuilder = new ProdViewArray.Builder();
            foreach (ProdDB prod in InnerSearchProdList(conditions))
            {
                arrayBuilder.ViewList.Add(ConverToView(prod));
            }

            return arrayBuilder.Build().ToByteArray();
        }

        public string SearchProdListToPDF(byte[] conditions)
        {
            ListGenerator generator = new ListGenerator();
            return generator.Generate(InnerSearchProdList(conditions), true);
        }

        public string SearchProdListToExcel(byte[] conditions)
        {
            ListGenerator generator = new ListGenerator();
            return generator.Generate(InnerSearchProdList(conditions));
        }

        #endregion

        #region 主要信息参数

        private PrimaryProd ConvertToPrimaryProd(ProdDB prod)
        {
            PrimaryProd.Builder builder = new PrimaryProd.Builder();
            builder.SetId(prod.Id.ToString());
            builder.SetProdClass(prod.ProdClass);

            if (!string.IsNullOrEmpty(prod.ProdLabel))
                builder.SetProdLabel(prod.ProdLabel);

            builder.SetProdPlace(prod.ProdPlace);

            if (!string.IsNullOrEmpty(prod.ProdSeries))
                builder.SetProdSeries(prod.ProdSeries);

            if (!string.IsNullOrEmpty(prod.ProdVersion))
                builder.SetProdVersion(prod.ProdVersion);

            if (!string.IsNullOrEmpty(prod.PhyColor))
                builder.SetPhyColor(prod.PhyColor);

            if (!string.IsNullOrEmpty(prod.PhyDefend))
                builder.SetPhyDefend(prod.PhyDefend);

            builder.SetPhyImpact(prod.PhyImpact);

            if (!string.IsNullOrEmpty(prod.PhySize))
                builder.SetPhySize(prod.PhySize);

            builder.SetAdpClass(prod.AdpClass);

            if (!string.IsNullOrEmpty(prod.AdpColor))
                builder.SetAdpColor(prod.AdpColor);

            builder.SetAdpCri(prod.AdpCri);
            builder.SetEleLgtPower(prod.EleLgtPower);

            if (!string.IsNullOrEmpty(prod.OptAngle))
                builder.SetOptAngle(prod.OptAngle);

            builder.SetProjSetup(prod.ProjSetup);
            builder.SetBusMarket(prod.BusMarket);

            if (!string.IsNullOrEmpty(prod.PicFacade))
                builder.SetPicFacade(string.Format("{0}/{1}", prod.PicFolder, prod.PicFacade));

            if (!string.IsNullOrEmpty(prod.PicGrading))
                builder.SetPicGrading(string.Format("{0}/{1}", prod.PicFolder, prod.PicGrading));

            if (!string.IsNullOrEmpty(prod.PicSize))
                builder.SetPicSize(string.Format("{0}/{1}", prod.PicFolder, prod.PicSize));

            if (!string.IsNullOrEmpty(prod.PicLive))
                builder.SetPicLive(string.Format("{0}/{1}", prod.PicFolder, prod.PicLive));
            return builder.Build();
        }

        // 四级页面
        public byte[] SearchPrimaryProdInfo(string id)
        {
            var prod = ProdArray.FindOne(Query.EQ("_id", ObjectId.Parse(id)));
            return prod != null ? ConvertToPrimaryProd(prod).ToByteArray() : null;
        }

        public string SearchPrimaryProdInfoToPDF(string id)
        {
            SpecGenerator generator = new SpecGenerator();
            return generator.Generate(GetProd(id), true);
        }

        public string SearchPrimaryProdInfoToExcel(string id)
        {
            SpecGenerator generator = new SpecGenerator();
            return generator.Generate(GetProd(id));
        }

        #endregion

        #region 详细信息
        // 五级页面
        public Prod ConvertTo(ProdDB prod)
        {
            Prod.Builder builder = new Prod.Builder();
            builder.SetId(prod.Id.ToString());
            builder.SetProdClass(prod.ProdClass);
            if (!string.IsNullOrEmpty(prod.ProdLabel))
                builder.SetProdLabel(prod.ProdLabel);
            builder.SetProdPlace(prod.ProdPlace);
            if (!string.IsNullOrEmpty(prod.ProdSeries))
                builder.SetProdSeries(prod.ProdSeries);
            if (!string.IsNullOrEmpty(prod.ProdVersion))
                builder.SetProdVersion(prod.ProdVersion);
            if (!string.IsNullOrEmpty(prod.PhyColor))
                builder.SetPhyColor(prod.PhyColor);
            if (!string.IsNullOrEmpty(prod.PhyDefend))
                builder.SetPhyDefend(prod.PhyDefend);
            builder.SetPhyImpact(prod.PhyImpact);
            if (!string.IsNullOrEmpty(prod.PhySize))
                builder.SetPhySize(prod.PhySize);
            builder.SetAdpClass(prod.AdpClass);
            if (!string.IsNullOrEmpty(prod.AdpColor))
                builder.SetAdpColor(prod.AdpColor);
            builder.SetAdpCri(prod.AdpCri);
            builder.SetEleLgtPower(prod.EleLgtPower);
            if (!string.IsNullOrEmpty(prod.OptAngle))
                builder.SetOptAngle(prod.OptAngle);
            builder.SetProjSetup(prod.ProjSetup);
            builder.SetBusMarket(prod.BusMarket);


            builder.SetProdOrgin(prod.ProdOrgin);
            if (!string.IsNullOrEmpty(prod.PhyMaterial))
                builder.SetPhyMaterial(prod.PhyMaterial);
            builder.SetPhyWeight(prod.PhyWeight);
            builder.SetOptExplain(prod.OptExplain);
            builder.SetOptEff(prod.OptEff);
            if (!string.IsNullOrEmpty(prod.EleShock))
                builder.SetEleShock(prod.EleShock);
            builder.SetEleVoltage(prod.EleVoltage);
            if (!string.IsNullOrEmpty(prod.EleType))
                builder.SetEleType(prod.EleType);
            builder.SetEleElecPower(prod.ElePower);
            builder.SetEleAllPower(prod.EleAllPower);
            builder.SetEleCtlType(prod.EleCtlType);
            if (!string.IsNullOrEmpty(prod.AdpVersion))
                builder.SetAdpVersion(prod.AdpVersion);
            builder.SetAdpOutput(prod.AdpOutput);
            if (!string.IsNullOrEmpty(prod.AdpPins))
                builder.SetAdpPins(prod.AdpPins);
            if (!string.IsNullOrEmpty(prod.ProjParts))
                builder.SetProjParts(prod.ProjParts);
            if (!string.IsNullOrEmpty(prod.ProjSize))
                builder.SetProjSize(prod.ProjSize);
            if (!string.IsNullOrEmpty(prod.ProjReport))
                builder.SetProjReport(prod.ProjReport);
            if (!string.IsNullOrEmpty(prod.ProjBaikup))
                builder.SetProjBaikup(prod.ProjBaikup);

            builder.SetBusIn(prod.BusIn);
            builder.SetBusOut(prod.BusOut);

            if (!string.IsNullOrEmpty(prod.BusExpires))
                builder.SetBusExpires(prod.BusExpires);

            if (!string.IsNullOrEmpty(prod.PicFolder))
            {
                builder.SetPicFolder(prod.PicFolder);
                if (!string.IsNullOrEmpty(prod.PicFacade))
                    builder.SetPicFacade(string.Format("{0}/{1}/{2}", prod.PicFolder, ProdDB.Zoom100, prod.PicFacade));
                if (!string.IsNullOrEmpty(prod.PicSize))
                    builder.SetPicSize(string.Format("{0}/{1}/{2}", prod.PicFolder, ProdDB.Zoom100, prod.PicSize));
                if (!string.IsNullOrEmpty(prod.PicGrading))
                    builder.SetPicGrading(string.Format("{0}/{1}/{2}", prod.PicFolder, ProdDB.Zoom100, prod.PicGrading));
                if (!string.IsNullOrEmpty(prod.PicLive))
                    builder.SetPicLive(string.Format("{0}/{1}/{2}", prod.PicFolder, ProdDB.Zoom100, prod.PicLive));
            }

            return builder.Build();
        }

        public byte[] SearchProdInfo(string id)
        {
            var prod = ProdArray.FindOne(Query.EQ("_id", ObjectId.Parse(id)));
            if (prod != null)
                return ConvertTo(prod).ToByteArray();
            return null;
        }

        public string SearchProdInfoToPDF(string id)
        {
            SpecAllGenerator generator = new SpecAllGenerator();
            return generator.Generate(GetProd(id), true);
        }

        public string SearchProdInfoToExcel(string id)
        {
            SpecAllGenerator generator = new SpecAllGenerator();
            return generator.Generate(GetProd(id));
        }

        #endregion

        #region 批量删除

        public bool BatchDeleteProd(byte[] bytes)
        {
            BatchDelete batchDelete = BatchDelete.ParseFrom(bytes);
            List<IMongoQuery> list = new List<IMongoQuery>();
            foreach (string str in batchDelete.Id.Split(','))
            {
                list.Add(Query.EQ("_id", ObjectId.Parse(str)));
            }

            return ProdArray.Remove(Query.Or(list.ToArray())).Ok;
        }

        #endregion

        #region 批量打印

        // 推荐商品
        public string CustomExportToExcel(byte[] bytes)
        {
            BatchDelete batchDelete = BatchDelete.ParseFrom(bytes);
            List<IMongoQuery> list = new List<IMongoQuery>();
            foreach (string str in batchDelete.Id.Split(','))
            {
                list.Add(Query.EQ("_id", ObjectId.Parse(str)));
            }

            ListGenerator generator = new ListGenerator();
            return generator.Generate(ProdArray.Find(Query.Or(list.ToArray())));
        }

        // 推荐商品
        public string CustomExportToPDF(byte[] bytes)
        {
            BatchDelete batchDelete = BatchDelete.ParseFrom(bytes);
            List<IMongoQuery> list = new List<IMongoQuery>();
            foreach (string str in batchDelete.Id.Split(','))
            {
                list.Add(Query.EQ("_id", ObjectId.Parse(str)));
            }

            ListGenerator generator = new ListGenerator();
            return generator.Generate(ProdArray.Find(Query.Or(list.ToArray())), true);
        }
        #endregion

        #region 搜索关联
        public byte[] SearchRelations(string id)
        {
            ProdDB source = ProdArray.FindOne(Query.EQ("_id", ObjectId.Parse(id)));
            if (source == null)
                return null;

            //ExpressionHandler handler = new VoltageHandler(null, source);
            //handler = new ShockHandler(handler, source);
            //handler = new DefendHandler(handler, source);
            //handler = new SetupHandler(handler, source);
            //handler = new OutputHandler(handler, source);
            //handler = new ColorHandler(handler, source);
            //handler = new AngleHandler(handler, source);
            //handler = new ExplainHandler(handler, source);
            //handler = new PlaceHandler(handler, source);

            ExpressionHandler handler = null;
            if (source.EleLgtPower == 0)
                handler = new OutputHandler(null, source);
            else
                handler = new PowerHandler(null, source);

            handler = new AngleHandler(handler, source);
            handler = new ClassHandler(handler, source);

            IList<ProdDB> query = (from r in ProdArray.FindAll()
                                   where r.Id.ToString() != id
                                       && !StringEquals(r.ProdLabel, source.ProdLabel)
                                   select r).ToList();
            query = handler.Filter(query);

            PrimaryProdArray.Builder arrayBuilder = new PrimaryProdArray.Builder();
            foreach (ProdDB item in query)
            {
                arrayBuilder.PrimaryProdList.Add(ConvertToPrimaryProd(item));
            }
            return arrayBuilder.Build().ToByteArray();
        }
        #endregion

        private bool StringEquals(string str1, string str2)
        {
            str1 = str1 == null ? string.Empty : str1;
            str2 = str2 == null ? string.Empty : str2;

            return str1.ToUpper() == str2.ToUpper();
        }

        #region 新品上架
        private DateTime? ParseTime(string s)
        {
            try
            {
                int year = int.Parse(s.Substring(0, 4));
                int month = int.Parse(s.Substring(4, 2));
                int day = int.Parse(s.Substring(6, 2));

                return new DateTime(year, month, day);
            }
            catch
            {
                return null;
            }
        }

        public byte[] SearchNewProds()
        {
            DateTime time = DateTime.Now.AddDays(-31);
            var query = from r in ProdArray.FindAll()
                        let targetTime = ParseTime(r.PicFolder)
                        where targetTime.HasValue && targetTime.Value >= time
                        orderby r.ProdLabel, r.PicFolder descending
                        select r;

            ProdViewArray.Builder arrayBuilder = new ProdViewArray.Builder();
            foreach (ProdDB prod in query)
            {
                arrayBuilder.ViewList.Add(ConverToView(prod));
            }

            return arrayBuilder.Build().ToByteArray();
        }

        public IEnumerable<ProdDB> InnerSearchNewProds()
        {
            DateTime time = DateTime.Now.AddDays(-31);
            var query = from r in ProdArray.FindAll()
                        let targetTime = ParseTime(r.PicFolder)
                        where targetTime.HasValue && targetTime.Value >= time
                        orderby r.ProdLabel, r.PicFolder descending
                        select r;

            return query;
        }

        public string SearchNewProdsToPDF()
        {
            ListGenerator generator = new ListGenerator();
            return generator.Generate(InnerSearchNewProds(), true);
        }

        public string SearchNewProdsToExcel()
        {
            ListGenerator generator = new ListGenerator();
            return generator.Generate(InnerSearchNewProds());
        }

        #endregion
    }
}
